package server;

import common.Constant;
import common.Message;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

import static common.Constant.SYSTEM;

class ServerThread implements Runnable {
    private UserInfo userInfo;
    private MessageSend messageSend;
    private Socket socket;

    public ServerThread(UserInfo userInfo, MessageSend messageSend, Socket socket) {
        this.userInfo = userInfo;
        this.messageSend = messageSend;
        this.socket = socket;
    }

    @Override
    public void run() {
        System.out.println("You have run a new ServerThread");
        BufferedReader bufferedReader = null;
        PrintWriter printWriter = null;
        try {
            //读取client传过来的数据
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //数据内容到client
            printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        String s = "";
        while (true) {
            try {
                s = bufferedReader.readLine();
            } catch (Exception e) {
                System.out.println("客户端关闭了连接");
                break;
            }
            if (s == null) {
                break;
            }
            if (s.contains(Constant.REGISTER)) {  // 登录请求
                //anny
                String username = Constant.decodeLogin(s);
                //userinfo=》db
                if (userInfo.isUserNameRegistered(username)) {
                    printWriter.println(Constant.REGISTER_FAILED);
                    printWriter.flush();
                } else {
                    printWriter.println(Constant.REGISTER_SUCCEED);
                    printWriter.flush();
                    Message message = new Message(SYSTEM,"Welcome "+username+" to join the chat");
                    //告诉anny注册进来之前存在的所有用户
                    messageSend.sentToAll(message);
                    //把anny添加进usernameset，printWriter是跟anny通信的通道，url，email
                    messageSend.add(username, printWriter);
                }
            } else if (s.contains(Constant.LOGOUT)) {  // 登出请求
                String username = Constant.decodeLogout(s);
                userInfo.logout(username);
                messageSend.remove(username);
            } else if (s.contains(Constant.MESSAGE)) {     // 发送消息请求（这里默认为广播，也就是全部发送）
                Message message = Constant.decodeMessage(s);
                messageSend.sentToAll(message);
            }
        }
        System.out.println("a serverThread is terminated");
    }
}

public class Server {
    //
    public Server() throws IOException {
        UserInfo userInfo = new UserInfo();
        MessageSend messageSend = new MessageSend();
        ServerSocket serverSocket = new ServerSocket(Constant.port);
        System.out.println("服务器已启动");
        while (true) {
            Socket socket = serverSocket.accept();
            String ip = socket.getInetAddress().getHostAddress();
            System.out.println("连接了一个ip： " + ip);
            new Thread(new ServerThread(userInfo, messageSend, socket)).start();
        }
    }

    public static void main(String[] args) throws IOException {
        new Server();
    }
}

class UserInfo {
    private Set<String> registeredUserNameSet = new HashSet<>();

    public UserInfo() {
        registeredUserNameSet.add(SYSTEM);
    }


    public boolean isUserNameRegistered(String username) {
        boolean contains = registeredUserNameSet.contains(username);
        if (contains){
            return true;
        }
        registeredUserNameSet.add(username);
        return false;
    }

    public void logout(String username){
        registeredUserNameSet.remove(username);
    }
}

class MessageSend {
    private HashMap<String, PrintWriter> users = new HashMap<>();

    //System代表server，null
    public MessageSend() {
        users.put("System",null);
    }

    public synchronized void add(String username, PrintWriter printWriter) {
        users.put(username, printWriter);
    }

    public synchronized void remove(String username) {
        users.remove(username);
    }


    public synchronized boolean sendTo(String toUsername, Message message) {
        if (Constant.SYSTEM.equals(toUsername)){
            return false;
        }
//        // 接受者或者发送者有不在线的，都发送失败
//        if (!users.containsKey(toUsername)) {
//            return false;
//        } else if (!users.containsKey(message.getFrom())) {
//            return false;
//        }
        try {
            users.get(toUsername).println(Constant.encodeMessage(message));
            users.get(toUsername).flush();
        } catch (Exception e) {
            // 如果发送失败，说明与toUsername的连接已经断开，将它踢出在线列表
            users.remove(toUsername);
            e.printStackTrace();
        }
        return true;
    }

    public synchronized void sentToAll(Message message) {
        PriorityQueue<Integer> integers = new PriorityQueue<>();
        integers.peek();
        for (String username : users.keySet()) {
            boolean isSent = sendTo(username, message);
            if (isSent) {
                System.out.println(message.getFrom() + " successfully send to " + username);
            }
        }
    }
}
